//
//  NSData+DYPNGChunk.m
//  DYNinePatchDemo
//
//  Created by 李松芮 on 2018/10/29.
//  Copyright © 2018 douyu. All rights reserved.
//

/**
 Demo:npTc type chunk
 
 0000003C # length
 6E705463 # "npTc"
 00 # wasDeserialized
 02 # numXDivs
 02 # numYDivs
 03 # numColors
 20000000 # *xDivsz
 28000000 # *yDivsz
 0000013F # paddingLeft
 00000044 # paddingRight
 0000003D # paddingTop
 00000039 # paddingBottom
 30000000 # *colors
 0000013F # stretch left
 00000147 # stretch right
 00000000 # stretch top
 0000009C # stretch bottom
 00000001 00000001 00000001 E4042807
 00002000 # CRC
 */

#import "NSData+DYPNGChunk.h"

static Byte kPNGSignature[8] = {137, 80, 78, 71, 13, 10, 26, 10};

@implementation NSData(DYPNGChunk)

- (UIImage *)dynp_resizableImage
{
    if (![self isPNGFile]) {
        return nil;
    }
    
    UIEdgeInsets resizableInset = UIEdgeInsetsZero;
    UIEdgeInsets contentInset = UIEdgeInsetsZero;
    [self scanNinePatchChunk:&resizableInset contentInset:&contentInset];
    UIImage *image = [[UIImage alloc] initWithData:self];
    image = [image resizableImageWithCapInsets:resizableInset resizingMode:UIImageResizingModeStretch];
    image.dynp_contentInset = contentInset;
    return image;
}

- (BOOL)isPNGFile
{
    BOOL isPNGFile = YES;
    Byte *signature = malloc(sizeof(Byte) * 8);
    [self getBytes:signature length:8];
    for (int index = 0; index < 8; index ++ ) {
        Byte data = signature[index];
        Byte s_data = kPNGSignature[index];
        if (data != s_data) {
            // 逐位比较文件签名
            isPNGFile = NO;
            break;
        }
    }
    free(signature);
    return isPNGFile;
}

- (void)scanNinePatchChunk:(UIEdgeInsets *)resizableInset contentInset:(UIEdgeInsets *)contentInset
{
    NSUInteger offset = 8; // 跳过文件签名
    unsigned int length = 0;
    char chunkType[4];
//    unsigned int crc[4];
    const char idat[4] = "IDAT"; // IDAT 图像数据
//    const char npol[4] = "NPOL"; // NPOL
    const char nptc[4] = "NPTC"; // NPTC
    
    while (1) {
        if (offset >= self.length) {
            break;
        }
        // length
        [self getBytes:&length range:NSMakeRange(offset, 4)];
        convertToLittleEndian(&length, 1);
        // header
        [self getBytes:chunkType range:NSMakeRange(offset + 4, 4)];
        /*
        // CRC
        [self getBytes:crc range:NSMakeRange(offset + 4 + length, 4)];
         */
        
        if ([self isChunkType:chunkType equalTo:nptc]) {
            // 解析点九图信息
            [self readNinePatchTypeChunk:offset + 4 + 4 resizableInset:resizableInset contentInset:contentInset];
            break;
        }
        
        if ([self isChunkType:chunkType equalTo:idat]) {
            // 进入图像数据区段，结束遍历
            break;
        }
        offset += (4 + 4 + length + 4);
    }
}

- (void)readNinePatchTypeChunk:(NSUInteger)offset resizableInset:(UIEdgeInsets *)resizableInset contentInset:(UIEdgeInsets *)contentInset
{
    // TODO:判断显示区域(optional)是否存在
    // 显示区域
    unsigned int leftPadding = 0,
                 rightPadding = 0,
                 topPadding = 0,
                 bottomPadding = 0;
    leftPadding = [self readUnsignedInt:offset + 12];
    rightPadding = [self readUnsignedInt:offset + 16];
    topPadding = [self readUnsignedInt:offset + 20];
    bottomPadding = [self readUnsignedInt:offset + 24];
    
    // 拉伸参数
    unsigned int leftStretch = 0,
                 rightStretch = 0,
                 topStretch = 0,
                 bottomStretch = 0;
    leftStretch = [self readUnsignedInt:offset + 32];
    rightStretch = [self readUnsignedInt:offset + 36];
    topStretch = [self readUnsignedInt:offset + 40];
    bottomStretch = [self readUnsignedInt:offset + 44];
    
    *resizableInset = UIEdgeInsetsMake(topStretch, leftStretch, bottomStretch, rightStretch);
    *contentInset = UIEdgeInsetsMake(topPadding, leftPadding, bottomPadding, rightPadding);
}

- (unsigned int)readUnsignedInt:(NSInteger)offset
{
    unsigned int num = 0;
    [self getBytes:&num range:NSMakeRange(offset, 4)];
    convertToLittleEndian(&num, 1);
    return num;
}

// 不区分大小写 比对4个Byte长度的chunk type
- (BOOL)isChunkType:(char [4])chunkType equalTo:(const char [4])type
{
    for (int index = 0; index < 4; index ++ ) {
        char left = [self lowerChar:chunkType[index]];
        char right = [self lowerChar:type[index]];;
        if ((left != right)) {
            return NO;
        }
    }
    return YES;
}

// 把char字母转换为小写
- (char)lowerChar:(char)ch
{
    if (ch < 97) { // 大写
        return ch + 32;
    }
    return ch;
}

- (BOOL)isArray:(Byte *)arr1 equalTo:(Byte *)arr2 length:(NSInteger)byteLength
{
    for (int index = 0; index < byteLength; index ++ ) {
        if (((Byte*)arr1)[index] != ((Byte*)arr2)[index]) {
            return NO;
        }
    }
    return YES;
}


static void convertToLittleEndian(unsigned int *data, int len)
{
    for (int index = 0; index < len; index ++) {
        
        *data = ((*data & 0xff000000) >> 24)
        | ((*data & 0x00ff0000) >>  8)
        | ((*data & 0x0000ff00) <<  8)
        | ((*data & 0x000000ff) << 24);
        
        data ++;
    }
}

@end
